
package sk.lieskove.jianghongtiao.aresapi.response.obj;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import sk.lieskove.jianghongtiao.common.utils.xml.ProcessXML;

import javax.persistence.*;
import javax.xml.xpath.XPathExpressionException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;



/**
 * <p>Java class for odpoved_fo complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="odpoved_fo">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="Pomocne_ID" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
 *         &lt;element name="Error" type="{http://wwwinfo.mfcr.cz/ares/xml_doc/schemas/ares/ares_datatypes/v_1.0.4}error_ARES" minOccurs="0"/>
 *         &lt;element name="Help" type="{http://wwwinfo.mfcr.cz/ares/xml_doc/schemas/ares/ares_datatypes/v_1.0.4}help_ARES" minOccurs="0"/>
 *         &lt;element name="V" type="{http://wwwinfo.mfcr.cz/ares/xml_doc/schemas/ares/ares_datatypes/v_1.0.4}vypis_stranky_fo" maxOccurs="unbounded" minOccurs="0"/>
 *         &lt;element name="Pocet_zaznamu" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@Entity
@Table(name="ares_odpoved_fo")
public class OdpovedFo implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    protected Integer pomocneID;
    @OneToOne
    protected ErrorARES error = null;
    @OneToOne(cascade=CascadeType.PERSIST, 
            fetch=FetchType.EAGER, targetEntity=HelpARES.class)
    protected HelpARES help = null;
    @OneToMany(mappedBy = "odpovedFo", cascade=CascadeType.PERSIST, 
            fetch=FetchType.EAGER, targetEntity=VypisStrankyFo.class)
    protected List<VypisStrankyFo> v = null;
    protected Integer pocetZaznamu;

    @Transient
    private Logger log = Logger.getLogger(OdpovedFo.class);
    @Transient
    private String xPath;
    @Transient
    private int nodePosition;
    @Transient
    private Document document;
    @ManyToOne
    private AresOdpovedi aresOdpovedi;

    public OdpovedFo() {
    }


    /**
     * set pomocne id from xml document
     */
    private void setPomocneId(){
        String pid = getValue("Pomocne_ID");
        if(pid != null){
            pomocneID = new Integer(pid);
        } else {
            pomocneID = null;
        }
    }

    /**
     * set pocet zaznamu from document
     */
    private void setPocetZaznamu(){
        String pz = getValue("Pocet_zaznamu");
        if(pz != null){
            pocetZaznamu = new Integer(pz);
        } else {
            pocetZaznamu = null;
        }
        
    }

    private void setAresError(){
        String xp = xPathConstructor("Error");
        log.debug("Loading '"+xp+"'");
        try {
            Node output = ProcessXML.getNodeByXPathQuery(xp, document);
            if (output == null) {
                log.warn("Cannot load: "+xp);
            } else {
                error = new ErrorARES(xp, document);
                error.setOdpovedFo(this);
            }
        } catch (XPathExpressionException ex) {
            log.warn("Cannot load '"+xp+"' property. ",ex);
        }
    }

    private void setHelpAres(){
        String xp = xPathConstructor("Help");
        log.debug("Loading '"+xp+"'");
        try {
            Node output = ProcessXML.getNodeByXPathQuery(xp, document);
            if (output == null) {
                log.warn("Cannot load: "+xp);
            } else {
                help = new HelpARES(xp, document);
                help.setOdpovedFo(this);
            }
        } catch (XPathExpressionException ex) {
            log.warn("Cannot load '"+xp+"' property. ",ex);
        }
    }

    private void setV(){
        String xp = xPathConstructor("V");
        log.debug("Loading '"+xp+"'");
        v = new ArrayList<VypisStrankyFo>();
        try {
            NodeList output = ProcessXML.getNodeListByXPathQuery(xp, document);
            if (output == null) {
                log.warn("Cannot load: "+xp);
            } else {
                for (int i = 0; i < output.getLength(); i++) {
                    VypisStrankyFo vypisStrankyFo = new VypisStrankyFo(xp, i+1, document);
                    vypisStrankyFo.setOdpovedFo(this);
                    v.add(vypisStrankyFo);
                }
            }
        } catch (XPathExpressionException ex) {
            log.warn("Cannot load '"+xp+"' property. ",ex);
        }
    }

    public OdpovedFo(String xPath, int nodePosition, Node node,
            Document document) {
        this.xPath = xPath;
        this.nodePosition = nodePosition;
        this.document = document;

        setPomocneId();
        setPocetZaznamu();
        setAresError();
        setHelpAres();
        setV();
    }

    /**
     * get value from xml document
     * @param nodeName name of node which we are going to select
     * @return text! value of node
     */
    private String getValue(String nodeName){
        String xp = xPathConstructor(nodeName);
        log.debug("Loading '"+xp+"'");
        try {
            Node output = ProcessXML.getNodeByXPathQuery(xp, document);
            if (output == null) {
                log.warn("Cannot load: "+xp);
            } else {
                return output.getTextContent();
            }
        } catch (XPathExpressionException ex) {
            log.warn("Cannot load '"+xp+"' property. ",ex);
        }
        return null;
    }

    /**
     * make xPath query by node and his position
     * @param subNode subnode which we are going to select
     * @return new xPath to select subnode with subNode name
     */
    private String xPathConstructor(String subNode){
        return xPath + "[" + nodePosition + "]/" + subNode;
    }

    public void setV(List<VypisStrankyFo> v) {
        this.v = v;
    }

    /**
     * Gets the value of the pomocneID property.
     * 
     * @return
     *     possible object is
     *     {@link Integer }
     *     
     */
    public Integer getPomocneID() {
        return pomocneID;
    }

    /**
     * Sets the value of the pomocneID property.
     * 
     * @param value
     *     allowed object is
     *     {@link Integer }
     *     
     */
    public void setPomocneID(Integer value) {
        this.pomocneID = value;
    }

    /**
     * Gets the value of the error property.
     * 
     * @return
     *     possible object is
     *     {@link ErrorARES }
     *     
     */
    public ErrorARES getError() {
        return error;
    }

    /**
     * Sets the value of the error property.
     * 
     * @param value
     *     allowed object is
     *     {@link ErrorARES }
     *     
     */
    public void setError(ErrorARES value) {
        this.error = value;
    }

    /**
     * Gets the value of the help property.
     * 
     * @return
     *     possible object is
     *     {@link HelpARES }
     *     
     */
    public HelpARES getHelp() {
        return help;
    }

    /**
     * Sets the value of the help property.
     * 
     * @param value
     *     allowed object is
     *     {@link HelpARES }
     *     
     */
    public void setHelp(HelpARES value) {
        this.help = value;
    }

    /**
     * Gets the value of the v property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the v property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getV().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link VypisStrankyFo }
     * 
     * 
     */
    public List<VypisStrankyFo> getV() {
        if (v == null) {
            v = new ArrayList<VypisStrankyFo>();
        }
        return this.v;
    }

    /**
     * Gets the value of the pocetZaznamu property.
     * 
     * @return
     *     possible object is
     *     {@link Integer }
     *     
     */
    public Integer getPocetZaznamu() {
        return pocetZaznamu;
    }

    /**
     * Sets the value of the pocetZaznamu property.
     * 
     * @param value
     *     allowed object is
     *     {@link Integer }
     *     
     */
    public void setPocetZaznamu(Integer value) {
        this.pocetZaznamu = value;
    }

    public AresOdpovedi getAresOdpovedi() {
        return aresOdpovedi;
    }

    public void setAresOdpovedi(AresOdpovedi aresOdpovedi) {
        this.aresOdpovedi = aresOdpovedi;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}
